package org.giovanolli.mumi.controller.business;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import javax.faces.event.AjaxBehaviorEvent;

import org.giovanolli.mumi.controller.AbstractController;
import org.giovanolli.mumi.controller.AbstractModel;
import org.giovanolli.mumi.controller.UseCaseMode;
import org.giovanolli.mumi.entities.AttentionTime;
import org.giovanolli.mumi.entities.Specialist;
import org.giovanolli.mumi.entities.filter.AttentionTimeFilter;
import org.giovanolli.mumi.entities.filter.PatientFilter;
import org.giovanolli.mumi.entities.filter.SpecialityFilter;
import org.giovanolli.mumi.service.AttentionTimeService;
import org.giovanolli.mumi.service.PatientService;
import org.giovanolli.mumi.service.Service;
import org.giovanolli.mumi.service.SpecialityService;
import org.primefaces.event.DateSelectEvent;
import org.primefaces.event.FlowEvent;
import org.primefaces.event.ScheduleEntrySelectEvent;
import org.primefaces.model.DefaultScheduleEvent;
import org.primefaces.model.DefaultScheduleModel;
import org.primefaces.model.ScheduleEvent;
import org.primefaces.model.ScheduleModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;

// TODO: Auto-generated Javadoc
/**
 * The Class AttentionTimeController.
 */
@Controller("attentionTimeController")
public class AttentionTimeController extends AbstractController<AttentionTime> {

	private static final String CONFIRM_AT_NEG_MESSAGE_KEY = "attentionTime.confirm.negativeBalance";

	private static final String CONFIRM_AT_OK_MESSAGE_KEY = "attentionTime.confirm.OK";

	/** The service. */
	@Autowired
	private AttentionTimeService service;

	/** The event model. */
	private ScheduleModel eventModel;

	/** The event. */
	private ScheduleEvent event = new DefaultScheduleEvent();

	/** The speciality service. */
	@Autowired
	private SpecialityService specialityService;

	/** The patient service. */
	@Autowired
	private PatientService patientService;

	/** The model. */
	@Autowired
	private AttentionTimeModel model;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.giovanolli.mumi.controller.AbstractController#init()
	 */
	@Override
	public void init() {
		super.init();
		model.setFilter(new AttentionTimeFilter());
		eventModel = new DefaultScheduleModel();
		populateNonEntityPropertiesToModel();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.giovanolli.mumi.controller.AbstractController#search()
	 */
	@Override
	@Transactional(readOnly = true)
	public void search() {
		eventModel = new DefaultScheduleModel();

		super.search();
		if (model.getList() != null) {
			Iterator<AttentionTime> it = model.getList().iterator();
			while (it.hasNext()) {
				AttentionTime attentionTime = it.next();
				String fullName = attentionTime.getPatient().getFullName();
				Date startEvent = attentionTime.getDate();
				Integer attentionTimeDuration = attentionTime.getSpecialistFee().getSpecialist().getAttentionTimeDuration();
				Date endEvent = new Date(startEvent.getTime() + (attentionTimeDuration * 60 * 1000));
				DefaultScheduleEvent scheduleEvent = new DefaultScheduleEvent(fullName, startEvent, endEvent);
				scheduleEvent.setId(attentionTime.getUid());
				scheduleEvent.setData(attentionTime);
				scheduleEvent.setStyleClass(Math.random() > 0.5 ? "fc-event-payed" : "fc-event-unpayed");
				eventModel.addEvent(scheduleEvent);
			}
		}

	}

	/**
	 * Prepare entity render.
	 * 
	 * @param uid
	 *            the uid
	 * @param useCaseMode
	 *            the use case mode
	 * @param specialist
	 *            the specialist
	 * @param timeAndDate
	 *            the time and date
	 * @throws InstantiationException
	 *             the instantiation exception
	 * @throws IllegalAccessException
	 *             the illegal access exception
	 */
	public void prepareEntityRender(String uid, UseCaseMode useCaseMode, Specialist specialist, Date timeAndDate) throws InstantiationException, IllegalAccessException {
		super.prepareEntityRender(uid, useCaseMode);
		if (specialist != null) {
			model.setSpecialist(specialist);
			model.setSelectableSpecialists(specialist.getSpeciality().getSpecialists());
			model.setSpeciality(specialist.getSpeciality());
		}
		if (timeAndDate != null) {
			model.setTimeAndDate(timeAndDate);
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.giovanolli.mumi.controller.AbstractController#bindModelToEntity()
	 */
	@Override
	protected void bindModelToEntity() {
		AttentionTime editedAttentionTime = model.getEditedEntity();
		editedAttentionTime.setDate(model.getTimeAndDate());
		editedAttentionTime.setAttentionOrder(model.getAttentionOrder());
		/* editedAttentionTime.setAssignedSpecialist(model.getSpecialist()); */
		editedAttentionTime.setPatient(model.getPatient());
		/*
		 * editedAttentionTime.setFee(model.getFee()); editedAttentionTime.setAttentionType (model.getSpecialistFee().getAttentionType());
		 */
		editedAttentionTime.setSpecialistFee(model.getSpecialistFee());
	}

	/**
	 * Bind entity.
	 */
	public void bindEntity() {
		bindModelToEntity();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.giovanolli.mumi.controller.AbstractController#bindEntityToModel()
	 */
	@Override
	protected void bindEntityToModel() {
		AttentionTime editedAttentionTime = model.getEditedEntity();
		model.setTimeAndDate(editedAttentionTime.getDate());
		model.setAttentionOrder(editedAttentionTime.getAttentionOrder());
		/*
		 * model.setSpecialist(editedAttentionTime.getAssignedSpecialist()); Specialist specialist = editedAttentionTime.getAssignedSpecialist();
		 */
		Specialist specialist = null;
		if (editedAttentionTime.getSpecialistFee() != null) {
			specialist = editedAttentionTime.getSpecialistFee().getSpecialist();
			model.setSpecialistFee(editedAttentionTime.getSpecialistFee());
			model.setFee(editedAttentionTime.getSpecialistFee().getAmount());
		}
		model.setSpecialist(specialist);
		if (specialist != null) {
			model.setSpeciality(specialist.getSpeciality());
			model.setSelectableSpecialists(specialist.getSpeciality().getSpecialists());
		}
		model.setPatient(editedAttentionTime.getPatient());

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.giovanolli.mumi.controller.AbstractController#getModel()
	 */
	@Override
	protected AbstractModel<AttentionTime> getModel() {
		return model;
	}

	/**
	 * Gets the event model.
	 * 
	 * @return the event model
	 */
	public ScheduleModel getEventModel() {
		return eventModel;
	}

	/**
	 * Sets the event model.
	 * 
	 * @param eventModel
	 *            the new event model
	 */
	public void setEventModel(ScheduleModel eventModel) {
		this.eventModel = eventModel;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.giovanolli.mumi.controller.AbstractController#getService()
	 */
	@Override
	protected Service<AttentionTime> getService() {
		return service;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.giovanolli.mumi.controller.AbstractController#getEntityClass()
	 */
	protected Class<AttentionTime> getEntityClass() {
		return AttentionTime.class;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.giovanolli.mumi.controller.AbstractController# populateNonEntityPropertiesToModel()
	 */
	@Override
	public void populateNonEntityPropertiesToModel() {
		model.setSelectableSpecialities(specialityService.getList(new SpecialityFilter()));
		model.setSelectablePatients(patientService.getList(new PatientFilter()));
	}

	// ///////////////////
	// METODOS DE CAMBIO DE COMBOS DE BUSQUEDA
	// //////////////////

	/**
	 * On speciality change.
	 * 
	 * @param actionEvent
	 *            the action event
	 */
	@Transactional(readOnly = true)
	public void onSpecialityChange(AjaxBehaviorEvent actionEvent) {
		model.setSelectableSpecialists(model.getSpeciality().getSpecialists());
	}

	/**
	 * On specialist change during SEARCH.
	 * 
	 * @param actionEvent
	 *            the action event
	 */
	public void onSpecialistChange(AjaxBehaviorEvent actionEvent) {
		eventModel = new DefaultScheduleModel();
		AttentionTimeFilter filter = new AttentionTimeFilter();
		filter.setSpecialist(model.getSpecialist());
		List<AttentionTime> attentionTimes = service.getList(filter);
		for (AttentionTime attentionTime : attentionTimes) {
			DefaultScheduleEvent scheduleEvent = new DefaultScheduleEvent(attentionTime.getPatient().getFullName(), attentionTime.getDate(), new Date(attentionTime.getDate()
					.getTime() + 1800000));
			scheduleEvent.setId(attentionTime.getUid());
			eventModel.addEvent(scheduleEvent);
		}
	}

	/**
	 * On specialist fee change.
	 * 
	 * @param actionEvent
	 *            the action event
	 */
	public void onSpecialistFeeChange(AjaxBehaviorEvent actionEvent) {
		model.setFee(model.getSpecialistFee().getAmount());
	}

	// ///////////////////////////////////
	// EVENTOS DE SELECCION DE FECHA / TURNO
	// //////////////////////////////////

	/**
	 * On event select.
	 * 
	 * @param selectEvent
	 *            the select event
	 */
	@Transactional(readOnly = true)
	public void onEventSelect(ScheduleEntrySelectEvent selectEvent) {
		event = selectEvent.getScheduleEvent();
		AttentionTime attentionTime = service.findByUid(((AttentionTime) event.getData()).getUid());
		model.setEditedEntity(attentionTime);

	}

	/**
	 * On date select.
	 * 
	 * @param selectEvent
	 *            the select event
	 */
	public void onDateSelect(DateSelectEvent selectEvent) {
		model.setTimeAndDate(selectEvent.getDate());
	}

	/**
	 * On flow process.
	 * 
	 * @param event
	 *            the event
	 * @return the string
	 */
	public String onFlowProcess(FlowEvent event) {
		return event.getNewStep();
	}

	@Transactional
	public void confirmAttentionTime(MessageContext messageContext, Locale locale) throws Exception {
		if (!patientService.isSolvent(model.getEditedEntity())) {
			messageContext.addMessage(new MessageBuilder().info().defaultText(messageSource.getMessage(CONFIRM_AT_NEG_MESSAGE_KEY, null, locale)).build());
		}
		messageContext.addMessage(new MessageBuilder().info().defaultText(messageSource.getMessage(CONFIRM_AT_OK_MESSAGE_KEY, null, locale)).build());
		service.confirmAttentionTime(model.getEditedEntity());
	}
}
